package com.raycloud.sdk.shopee;

import com.alibaba.fastjson.JSON;
import com.raycloud.sdk.shopee.exception.ApiException;
import com.raycloud.sdk.shopee.request.ShopeeRequest;
import com.raycloud.sdk.shopee.response.ShopeeResponse;
import com.raycloud.sdk.shopee.util.RequestParametersHolder;
import com.raycloud.sdk.shopee.util.ShopeeUtils;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.params.ClientPNames;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.PoolingClientConnectionManager;
import org.apache.http.message.BasicHeader;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.CoreConnectionPNames;
import org.apache.http.params.HttpParams;
import org.apache.http.util.EntityUtils;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by donar on 17/6/12.
 */
public class DefaultShopeeClient implements ShopeeClient {
    private static final String TIMESTAMP = "timestamp";
    private String serverUrl = "http://api.superseller.cn/api/v1";
    private boolean needCheckParam = true;
    private static final String AUTHORIZATION = "Authorization";
    private static final String CONTENTTYPE = "Content-Type";
    private static PoolingClientConnectionManager conMgr = null;
    static {
        HttpParams params = new BasicHttpParams();
        Integer CONNECTION_TIMEOUT = 2 * 1000; //设置请求超时2秒钟 根据业务调整
        Integer SO_TIMEOUT = 2 * 1000; //设置等待数据超时时间2秒钟 根据业务调整
        Long CONN_MANAGER_TIMEOUT = 500L; //该值就是连接不够用的时候等待超时时间，一定要设置，而且不能太大
        params.setIntParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, CONNECTION_TIMEOUT);
        params.setIntParameter(CoreConnectionPNames.SO_TIMEOUT, SO_TIMEOUT);
        params.setLongParameter(ClientPNames.CONN_MANAGER_TIMEOUT, CONN_MANAGER_TIMEOUT);
        params.setBooleanParameter(CoreConnectionPNames.STALE_CONNECTION_CHECK, true);
        conMgr = new PoolingClientConnectionManager();
        conMgr.setMaxTotal(2000);
        conMgr.setDefaultMaxPerRoute(conMgr.getMaxTotal());
    }
    private static DefaultHttpClient httpClient = new DefaultHttpClient(conMgr);
    @Override
    public <T extends ShopeeResponse> T execute(ShopeeRequest<T> request) throws ApiException {
        if (needCheckParam) {
            request.check();
        }
        return (T) doPost(request).get("rsp");
    }

    private  <T extends ShopeeResponse> Map<String, Object> doPost(ShopeeRequest<T> request) throws ApiException {
        CloseableHttpResponse res = null;
        try {

            Map<String, Object> result = new HashMap<String, Object>();
            RequestParametersHolder requestHolder = new RequestParametersHolder();
            HashMap appParams = new HashMap(request.getParams());
            Long timestamp = request.getTimestamp();// 允许用户设置时间戳
            if (timestamp == null) {
                timestamp = ShopeeUtils.getUnixTime();
            }
            appParams.put(TIMESTAMP, timestamp);
            requestHolder.setApplicationParams(appParams);
            // 添加协议级请求参数
            HashMap protocalMustParams = new HashMap();
            String urlPath = serverUrl + request.getApiMethodName();
            protocalMustParams.put(AUTHORIZATION, ShopeeUtils.getSHA256Secret(urlPath, JSON.toJSONString(requestHolder.getApplicationParams()), request.getSecretKey()));
            protocalMustParams.put(CONTENTTYPE, "application/json");
            requestHolder.setProtocalMustParams(protocalMustParams);
            HttpPost post = new HttpPost(urlPath);
            for (Map.Entry<String, String> entry : requestHolder.getProtocalMustParams().entrySet()) {
                post.addHeader(new BasicHeader(entry.getKey(), entry.getValue()));
            }
            StringEntity entity = null;
            entity = new StringEntity(JSON.toJSONString(requestHolder.getApplicationParams()));
            entity.setContentEncoding("UTF-8");
            entity.setContentType("application/json");
            post.setEntity(entity);
            res = httpClient.execute(post);
            switch (res.getStatusLine().getStatusCode()) {
                case 200:
                    String body = EntityUtils.toString(res.getEntity());
                    ShopeeResponse rsp = request.getResponseClass().newInstance();
                    rsp.setBody(body);
                    result.put("rsp", rsp);
                    break;
                case 400:
                    throw new ApiException("error_param");
                case 403:
                    throw new ApiException("error_auth");
                case 500:
                    throw new ApiException("error_server");
                default:
                    throw new ApiException("error_unknown");
            }

            result.put("appParams", appParams);
            result.put("protocalMustParams", protocalMustParams);
            result.put("url", urlPath);
            return result;
        } catch (Exception e) {
            if (e instanceof ApiException) {
                throw (ApiException)e;
            }else if(e instanceof IOException){
                e.printStackTrace();
            }else{
                e.printStackTrace();
                throw new RuntimeException("client error");
            }
        }finally {
            try {
                if(res!=null)res.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

}
